package de.akabahn.ebd.stw.zdxfc.prs.fst.impair;

import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.AUFLOESUNG_OK;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.FAHRSTRASSE_NH;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.GLEIS_11;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.GLEIS_14;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.MELDER_TASTE_NH;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_CV11;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_CV121;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_CV122;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.SIGNAL_CV123;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.WEICHE_10;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.WEICHE_110;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.WEICHE_9;
import de.akabahn.ebd.comm.dbd.DBDParameter;
import de.akabahn.ebd.dbd.SwitchPosition;
import de.akabahn.ebd.dbd.impl.DBDSignalF;
import de.akabahn.ebd.stw.zdxfc.prs.ZDXFCMain;
import de.akabahn.ebd.stw.zdxfc.prs.fst.FahrStrasse;

/**
 * Fahrstrasse <code>NH</code><br>
 * Start: Signal CV11<br>
 * Ziel: Signal CV5 Gleis 11<br>
 * <br>
 * Fahrstrassen Weichen:<br>
 * <ol>
 * <li>Weiche 9, Linkslage (Flankenschutz)</li>
 * <li>Weiche 10, Linkslage</li>
 * <li>Weiche 110, Linkslage</li>
 * </ol>
 * <br>
 * Fahrstrassen Gleise:<br>
 * <ol>
 * <li>Gleis 11 (Zielgleis, darf besetzt sein)</li>
 * </ol>
 * <br>
 * Fahrstrassen Signale:<br>
 * <ol>
 * <li>Signal Cv11, Startsignal, kein manueller Haltfall</li>
 * <li>Signal Cv121, Lichtschutz</li>
 * <li>Signal Cv122, Lichtschutz</li>
 * <li>Signal Cv123, Lichtschutz</li>
 * </ol>
 * 
 * @author Peter Eimann
 * @since 1.0
 * @version 1.2
 */
public class FahrStrasseNH extends FahrStrasse {

	/**
	 * Initialisierung mit ID <code>NH</code> und DBD-Name des Tastenmelders <code>S31TNHS</code>
	 * 
	 * @param main Referenz auf die Hauptklasse
	 */
	public FahrStrasseNH(ZDXFCMain main) {
		super(FAHRSTRASSE_NH, MELDER_TASTE_NH, main, SIGNAL_CV11);

		fstWeichen = new FstWeiche[] {
				new FstWeiche(WEICHE_9, SwitchPosition.LEFT, true),
				new FstWeiche(WEICHE_10, SwitchPosition.LEFT, false),
				new FstWeiche(WEICHE_110, SwitchPosition.LEFT, false)
		};
		
		fstGleise = new FstGleis[] {
				new FstGleis(GLEIS_11, false)
		};
		
		fstSignale = new FstSignal[] {
				new FstSignal(SIGNAL_CV11, true),
				new FstSignal(SIGNAL_CV121, false),
				new FstSignal(SIGNAL_CV122, false),
				new FstSignal(SIGNAL_CV123, false)
		};
	}

	/**
	 * Verschluss:<br>
	 * <ul>
	 * <li>Verschluss nur, wenn Gleis <code>14</code> besetzt ist</li>
	 * </ul>
	 * <br>
	 * Startsignal CV11:<br>
	 * <ul>
	 * <li>Fahrstrassen-ID <code>NH</code></li>
	 * <li>Signalbegriff <code>M</code></li>
	 * </ul>
	 */
	@Override
	public void einstellenProcess() {
		if (main.getGleis(GLEIS_14).isBesetzt()) {
			setVerschlossen(true);
		}

		main.getSignal(SIGNAL_CV11).setFahrStrassenId(id);
		main.getSignal(SIGNAL_CV11).stellen(DBDSignalF.M);
	}

	/**
	 * Ueberpruefte Bedingungen:<br>
	 * <ol>
	 * <li>Aufloesezeit muss kleiner gleich 0 sein</li>
	 * </ol>
	 * <br>
	 * Aktionen bei erfolgreicher Pruefung:<br>
	 * <ol>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 */
	@Override
	public boolean aufloeseBedinungenOk() {
		if (getAufloeseZeit() <= 0) {
			haltfallStartsignale();
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Wird als Aufloesezeit <code>0</code> uebergeben, wird die Fahrstrasse direkt aufgeloest (ohne weitere
	 * Bedienungshandlung)
	 */
	@Override
	public void setAufloeseZeit(long aufloeseZeit) {
		super.setAufloeseZeit(aufloeseZeit);
		
		if (aufloeseZeit == AUFLOESUNG_OK) {
			aufloesen();
		}
	}

	/**
	 * Ueberwachte Elemente:<br>
	 * <ol>
	 * <li>Weiche 110</li>
	 * <li>Weiche 10</li>
	 * <li>Gleis 11</li>
	 * <li>Gleis 14</li>
	 * </ol>
	 */
	@Override
	public void onChangeBesetzung(DBDParameter dbd) {
		if (dbd.getId().equals(WEICHE_110)) {
			onChangeWeiche110();
		} else if (dbd.getId().equals(WEICHE_10)) {
			onChangeWeiche10();
		} else if (dbd.getId().equals(GLEIS_11)) {
			onChangeGleis11();
		} else if (dbd.getId().equals(GLEIS_14)) {
			onChangeGleis14();
		}
	}

	/**
	 * Ueberwachung der Weiche 110:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Aufloesung Weiche 110 vorbereiten</li>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ol>
	 * <li>Verschluss der Fahrstrasse aufloesen</li>
	 * <li>Flankenschutz <code>Weiche 9</code> aufloesen</li>
	 * <li>Ausleuchtung Tastenmelder der Fahrstrasse loeschen</li>
	 * <li>Weiche 110 inaktiv setzen</li>
	 * </ol> 
	 */
	private void onChangeWeiche110() {
		if (main.getWeiche(WEICHE_110).isBesetzt()) {
			main.getWeiche(WEICHE_110).setAufloesenVorbereiten(true);
			haltfallStartsignale();
		} else {
			if (main.getWeiche(WEICHE_110).isAufloesenVorbereiten()) {
				main.getWeiche(WEICHE_110).setAufloesenVorbereiten(false);
				main.getWeiche(WEICHE_110).setAktiv(false);
				setVerschlossen(false);
				main.getWeiche(WEICHE_9).setFlankenSchutz(false);
				main.getDbd().set(getTastenMelderId(), 0);
			}
		}
	}

	/**
	 * Ueberwachung der Weiche 10:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Aufloesung Weiche 10 vorbereiten</li>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ol>
	 * <li>Fahrstrasse und <code>Gleis 11</code> inaktiv setzen</li>
	 * <li>Weiche 10 inaktiv setzen</li>
	 * </ol> 
	 */
	private void onChangeWeiche10() {
		if (main.getWeiche(WEICHE_10).isBesetzt()) {
			main.getWeiche(WEICHE_10).setAufloesenVorbereiten(true);
			haltfallStartsignale();
		} else {
			if (main.getWeiche(WEICHE_10).isAufloesenVorbereiten() && main.getGleis(GLEIS_11).isBesetzt()) {
				main.getWeiche(WEICHE_10).setAufloesenVorbereiten(false);
				main.getWeiche(WEICHE_10).setAktiv(false);
				main.getGleis(GLEIS_11).setAktiv(false);
				setAktiv(false);
			}
		}
	}
	
	/**
	 * Ueberwachung des Gleises 11:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Haltfall Startsignale</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ul>
	 * <li><i>keine</i></li>
	 * </ul> 
	 */
	private void onChangeGleis11() {
		if (main.getGleis(GLEIS_11).isBesetzt()) {
			haltfallStartsignale();
		}
	}

	/**
	 * Ueberwachung des Gleises 14:<br>
	 * Aktionen beim Besetzen:<br>
	 * <ol>
	 * <li>Verschluss der Fahrstrasse</li>
	 * </ol>
	 * <br>
	 * Aktionen beim Freifahren:<br>
	 * <ul>
	 * <li><i>keine</i></li>
	 * </ul> 
	 */
	private void onChangeGleis14() {
		if (main.getGleis(GLEIS_14).isBesetzt()) {
			setVerschlossen(true);
		}
	}
}
